#include <cv_bridge/cv_bridge.h>
#include <image_transport/image_transport.h>
#include <ros/ros.h>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/imgproc/types_c.h>

using namespace std;
using namespace cv;

int main(int argc, char **argv) {
  cv::Mat image = cv::imread(argv[1], CV_LOAD_IMAGE_COLOR);
  // cv::Mat image = cv::imread("/home/bianxu/tools/test.jpg",
  // CV_LOAD_IMAGE_COLOR);
  if (image.empty()) {
    printf("open error\n");
  }
  imshow("image", image);

  //图像滤波
  Mat out;
  medianBlur(image, out, 5); //孔径线性尺寸为5
  imshow("image1", out);
  image = out;

  //图像增强
  Mat imageLog(image.size(), CV_32FC3);
  for (int i = 0; i < image.rows; i++) {
    for (int j = 0; j < image.cols; j++) {
      imageLog.at<Vec3f>(i, j)[0] = log(1 + image.at<Vec3b>(i, j)[0]);
      imageLog.at<Vec3f>(i, j)[1] = log(1 + image.at<Vec3b>(i, j)[1]);
      imageLog.at<Vec3f>(i, j)[2] = log(1 + image.at<Vec3b>(i, j)[2]);
    }
  }
  //归一化到0~255
  normalize(imageLog, imageLog, 0, 255, CV_MINMAX);
  //转换成8bit图像显示
  convertScaleAbs(imageLog, imageLog);
  imshow("imageEnhance2", imageLog);

  //灰度化
  Mat gray;
  cvtColor(imageLog, gray, CV_RGB2GRAY);
  imshow("imagegray", gray);

  //二值化
  Mat binaryimage;
  binaryimage = image.clone();
  //进行二值化处理，选择30，255.0为阈值
  threshold(gray, binaryimage, 220, 255.0, CV_THRESH_BINARY);
  imshow("binaryimage", binaryimage);

  //腐蚀和膨胀操作
  Mat element1 = getStructuringElement(MORPH_RECT, Size(5, 5)); //获取自定义核
  Mat element2 = getStructuringElement(MORPH_RECT, Size(4, 4));
  Mat out1, out2;
  erode(binaryimage, out1, element1);
  dilate(out1, out2, element2);
  imshow("dstimage", out2);

  vector< vector<Point> > contours;
  vector<Vec4i> hierarchy;
  findContours(out2, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE,
               Point());
  Mat imageContours = Mat::zeros(image.size(), CV_8UC1);
  Mat Contours = Mat::zeros(image.size(), CV_8UC1); //绘制
  for (int i = 0; i < contours.size(); i++) {
    // contours[i]代表的是第i个轮廓，contours[i].size()代表的是第i个轮廓上所有的像素点数
    for (int j = 0; j < contours[i].size(); j++) {
      //绘制出contours向量内所有的像素点
      Point P = Point(contours[i][j].x, contours[i][j].y);
      Contours.at<uchar>(P) = 255;
    }
    //绘制轮廓
    drawContours(imageContours, contours, i, Scalar(255), 1, 8, hierarchy);
  }
  imshow("Contours Image", imageContours); //轮廓

  cv::waitKey(0);
}

//针对黑底红色数码管进行灰度化和二值化处理